package com.example.audio_test.ui

import android.Manifest
import android.media.*
import android.os.Environment
import android.util.Log
import com.alibaba.android.arouter.facade.annotation.Route
import com.example.audio_test.R
import com.example.audio_test.config.GlobalConfig.Companion.AUDIO_FORMAT
import com.example.audio_test.config.GlobalConfig.Companion.CHANNEL_CONFIG
import com.example.audio_test.config.GlobalConfig.Companion.SAMPLE_RATE
import com.example.audio_test.utils.PcmToWavUtils
import com.kun.base.ui.AbsBaseActivity
import com.kun.base.util.LogUtils
import kotlinx.android.synthetic.main.activity_record.*
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import permissions.dispatcher.*
import java.io.*

/**
 *录音的activity
 *
 * @author : Kun
 * @date : 2021/6/18
 * @time : 14:00
 */
@RuntimePermissions
@Route(path = "/recordTest/RecordActivity")
class RecordActivity : AbsBaseActivity() {

    var audioRecord: AudioRecord? = null
    var isRecording = false

    override fun getLayoutId(): Int {
        return R.layout.activity_record
    }

    override fun initViewModel() {
    }

    override fun initView() {
        btn_start.setOnClickListener {
            startRecordWithPermissionCheck()
        }

        btn_end.setOnClickListener {
            stopRecord()
        }

        btn_format.setOnClickListener {
            val pcwToWavUtils = PcmToWavUtils(
                SAMPLE_RATE, CHANNEL_CONFIG,
                AUDIO_FORMAT
            )
            val pcmFile = File(getExternalFilesDir(Environment.DIRECTORY_MUSIC), "test.pcm")
            val wavFile = File(getExternalFilesDir(Environment.DIRECTORY_MUSIC), "test.wav")
            if (!wavFile.mkdirs()) {
                LogUtils.e("wavFile Directory not created")
            }
            if (wavFile.exists()) {
                wavFile.delete()
            }
            pcwToWavUtils.pcmToWav(pcmFile.absolutePath, wavFile.absolutePath)
        }

        btn_play.setOnClickListener {
            playAudio()
        }
    }

    /**
     * 开始录音
     */
    @NeedsPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.RECORD_AUDIO)
    fun startRecord() {
        if (isRecording) {
            return
        }
        val miniRecordBuffSize = AudioRecord.getMinBufferSize(
            SAMPLE_RATE, CHANNEL_CONFIG,
            AUDIO_FORMAT
        )

        audioRecord = AudioRecord(
            MediaRecorder.AudioSource.MIC, SAMPLE_RATE, CHANNEL_CONFIG,
            AUDIO_FORMAT, miniRecordBuffSize
        )

        val data = ByteArray(miniRecordBuffSize)
        val file = File(getExternalFilesDir(Environment.DIRECTORY_MUSIC), "test.pcm")
        if (!file.mkdirs()) {
            Log.e("RecordActivity", "Directory not created")
        }
        if (file.exists()) {
            file.delete()
        }

        audioRecord!!.startRecording()
        isRecording = true

        GlobalScope.launch {
            var os: FileOutputStream? = null

            try {
                os = FileOutputStream(file)
            } catch (e: FileNotFoundException) {
                e.printStackTrace()
            }

            while (isRecording) {
                val read = audioRecord!!.read(data, 0, miniRecordBuffSize)

                if (read != AudioRecord.ERROR_INVALID_OPERATION) {
                    try {
                        os!!.write(data)
                    } catch (e: Exception) {
                        e.printStackTrace()
                    }
                }

            }

            try {
                os!!.close()
            } catch (e: Exception) {
                e.printStackTrace()
            }

            LogUtils.e("录制完成啦啦啦啦啦啦啦啦啦")
        }
    }

    /**
     * 停止录制
     */
    private fun stopRecord() {
        isRecording = false
        if (audioRecord != null) {
            audioRecord!!.stop()
            audioRecord!!.release()
            audioRecord = null
        }


    }

    /**
     * 播放音频
     */
    private fun playAudio() {
        val channelConfig = AudioFormat.CHANNEL_OUT_MONO

        val minBufferSize = AudioTrack.getMinBufferSize(SAMPLE_RATE, channelConfig, AUDIO_FORMAT)
        val audioTrack = AudioTrack(
            AudioAttributes.Builder()
                .setUsage(AudioAttributes.USAGE_MEDIA)
                .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
                .build(),
            AudioFormat.Builder()
                .setEncoding(AUDIO_FORMAT)
                .setSampleRate(SAMPLE_RATE)
                .setChannelMask(channelConfig)
                .build(),
            minBufferSize,
            AudioTrack.MODE_STREAM,
            AudioManager.AUDIO_SESSION_ID_GENERATE
        )
        audioTrack.play()

        val pcmFile = File(getExternalFilesDir(Environment.DIRECTORY_MUSIC), "test.pcm")

        try {
            val fileInputStream = FileInputStream(pcmFile)
            GlobalScope.launch {
                try {
                    val tempBuffer = ByteArray(minBufferSize)
                    while (fileInputStream.available() > 0) {
                        val readCount = fileInputStream.read(tempBuffer)
                        if (readCount == AudioTrack.ERROR_INVALID_OPERATION ||
                            readCount == AudioTrack.ERROR_BAD_VALUE
                        ) {
                            continue
                        }
                        if (readCount != 0 && readCount != -1) {
                            audioTrack.write(tempBuffer, 0, readCount)
                        }
                    }
                } catch (e: IOException) {
                    e.printStackTrace()
                }
            }

        } catch (e: IOException) {
            e.printStackTrace()
        }
    }

    /**
     *
     */
    @OnShowRationale(Manifest.permission.RECORD_AUDIO)
    fun showRationaleForCamera(request: PermissionRequest) {
        LogUtils.e("提示信息")
    }

    @OnPermissionDenied(Manifest.permission.RECORD_AUDIO)
    fun onCameraDenied() {
        LogUtils.e("权限拒绝")
    }

    @OnNeverAskAgain(Manifest.permission.RECORD_AUDIO)
    fun onCameraNeverAskAgain() {
        LogUtils.e("不在提醒")
    }

    override fun onRequestPermissionsResult(
        requestCode: Int,
        permissions: Array<out String>,
        grantResults: IntArray
    ) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults)
        onRequestPermissionsResult(requestCode, grantResults)
    }
}